home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / yamp16.zip / VIRTGRAF.CPP < prev    next >
C/C++ Source or Header  |  1993-01-11  |  17KB  |  681 lines

  1.  
  2. /*
  3. YAMP - Yet Another Matrix Program
  4. Version: 1.6
  5. Author: Mark Von Tress, Ph.D.
  6. Date: 01/11/93  
  7.  
  8. Copyright(c) Mark Von Tress 1993
  9. Portions of this code are (c) 1991 by Allen I. Holub and are used by
  10. permission
  11.  
  12. DISCLAIMER: THIS PROGRAM IS PROVIDED AS IS, WITHOUT ANY
  13. WARRANTY, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  14. TO FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR DISCLAIMS
  15. ALL LIABILITY FOR DIRECT OR CONSEQUENTIAL DAMAGES RESULTING
  16. FROM USE OF THIS PROGRAM.
  17.  
  18. */
  19.  
  20. #include "virt.h"
  21.  
  22. Axis::Axis(VMatrix &grf_vec, int col, int pixels, int pxlspplot)
  23. {
  24.     Dispatch->Inclevel();
  25.     getlinesettings(&lineinfo);
  26.     valmin = 0;
  27.     step = 0;
  28.     ir = 0;
  29.     ifault = 0;
  30.     iv = 30;
  31.     maxpr = 6;
  32.     mpv = pxlspplot;
  33.     fmn = fmx = grf_vec.m(1, col);
  34.     double temp;
  35.     for (int i = 2; i <= grf_vec.r; i++) {
  36.         temp = grf_vec.m(i, col);
  37.         fmn = (temp < fmn) ? temp : fmn;
  38.         fmx = (temp > fmx) ? temp : fmx;
  39.     }
  40.     if (fmn == fmx) {
  41.         fmx = fmn + 0.5;
  42.         fmn = fmn - 0.5;
  43.     }
  44.     
  45.     vals = new double[iv];
  46.     getvals(fmn, fmx, pixels, vals, &offset, &ifact, &nvals, &irprin);
  47.     Vals = new VMatrix;
  48.     *Vals = Fill(nvals, 1, 0);
  49.     for (i = 0; i < nvals; i++) {
  50.         double temp = (irprin != 0) ?
  51.             floor(0.5 + vals[i] *exp(((double) irprin) *log(10.0)))
  52.                 *exp(- ((double) irprin) *log(10.0)) :
  53.                 vals[i];
  54.                 Vals->M(i + 1, 1) = temp;
  55.     }
  56.     Dispatch->Declevel();
  57.     
  58. }
  59. Axis::~Axis(void)
  60. {
  61.     delete vals;
  62.     delete Vals;
  63. }
  64. double Axis::dmax(double x, double y)
  65. {
  66.     return ((x > y) ? x : y);
  67. }
  68.  
  69. void Axis::scale(double fmn, double fmx, int n, int mpv,
  70.     double *valmin, double *step, int *nvals, int *ir, int *ifault)
  71. { double unit[13] = { 0, 12, 15, 20, 25, 30, 40, 50, 60, 80, 100, 120, 150};
  72.             double tol = 5.0e-6, bias = 1.0e-5, cover = 0.7, temp;
  73.             int i, j, minn = 2, maxn = 10000;
  74.             char buf[80] = { '\0' };
  75.  
  76.             double fmax, fmin, finter, s, aj, tstep;
  77.             int nunit = 12;
  78.  
  79.             fmax = fmx;
  80.             fmin = fmn;
  81.             *ifault = 0;
  82.             if (fmax < fmin) *ifault++;
  83.             if ((n < minn) || (n > maxn)) *ifault += 2;
  84.             if ((mpv <= 0) || (mpv >= n)) *ifault += 4;
  85.             if (*ifault) {
  86.                 sprintf(buf, "SCALE: bad parameters in scale irprn = %d", *ifault);
  87.                 closegraph();
  88.                 Dispatch->Nrerror(buf);
  89.             }
  90.             *nvals = 1+ (n - 1) / mpv;
  91.             if ((fmax - fmin) <= (tol*((double) dmax(fabs(fmax), fabs(fmin))))){
  92.                 *ifault = -1;
  93.                 if (fmax < 0) fmax = 0;
  94.                 if (fmax == 0) fmax = 1;
  95.                 if (fmax > 0) fmin = 0;
  96.             }
  97.             finter =((double) n) / ((double) mpv);
  98.             s =(fmax - fmin) *(1.0+2.0*bias) / finter;
  99.             *ir = 0;
  100.             while (s <= 10.0) {
  101.                 s *= 10;
  102.                 (*ir)++;
  103.             }
  104.             while (s > 100) {
  105.                 s /= 10;
  106.                 (*ir)--;
  107.             }
  108.             i = 0;
  109.             while (s > unit[i]) i++;
  110.  
  111.             LABEL1 :
  112.             *step = unit[i] *exp(- ((double) (*ir)) *log(10));
  113.             aj = 0;
  114.  
  115.             LABEL2 :
  116.             do {
  117.                 aj += 1.0;
  118.             } while ((unit[i] - 0.1) > (floor((unit[i] + 0.1) / aj) *aj));
  119.             tstep = (*step) / aj;
  120.             temp = fmin / tstep + aj*(0.5 / ((double) mpv) - finter*bias);
  121.             *valmin = floor(temp) *tstep;
  122.             if ((temp < 0) && (temp != floor(temp))) (*valmin) -= tstep;
  123.             if (fmax < ((*valmin) +(*step) *(finter*(1.0-bias) - 0.5 / ((double)mpv))))
  124.                            goto LABEL3;
  125.             if ((unit[i] / unit[i + 1] *(1.0-1.0 / (aj*finter))) < cover) goto LABEL2;
  126.             i++;
  127.             if (i == nunit) printf("problem");
  128.             goto LABEL1;
  129.             LABEL3 :
  130.             for (j = 1; j <= 2; j++) {
  131.                 aj *= 10;
  132.                 if ((unit[i] - 0.1) < (floor((unit[i] + 0.1) / aj) *aj)) (*ir) -= 1;
  133.             }
  134. }     /* scale */
  135.  
  136.  
  137.  
  138. void Axis::axis(double valmin, double step, int nvals, int maxpr, int ir,
  139.     int *irprin, double *offset, int *ifact, double *vals, int iv,
  140.     int *ifault)
  141. {
  142.     int irmax = 200, mprmax = 20;
  143.     double fmax, tmax, fl, fs, vstep, vmin, temp1 = 0, temp2 = 0;
  144.     double dtemp1 = 0, dtemp2 = 0;
  145.     int i, il, is, it, ilprin;
  146.     char buf[80] = { '\0' };
  147.  
  148.     *ifault = 0;
  149.     if (nvals < 2) (*ifault)++;
  150.     fmax = valmin + step*((double) (nvals - 1));
  151.     if ((nvals >= 2) && (fmax <= valmin)) (*ifault) += 2;
  152.     if ((maxpr < 2) || (maxpr > mprmax)) (*ifault) += 4;
  153.     if (nvals > iv) (*ifault) += 8;
  154.     if (ir > irmax) (*ifault) += 16;
  155.     if (*ifault) {
  156.         sprintf(buf, "Axis: bad parameters in axis: error %d", *ifault);
  157.         closegraph();
  158.         Dispatch->Nrerror(buf);
  159.     }
  160.  
  161.     tmax = exp(((double) maxpr) *log(10.0));
  162.     fl = fabs(fmax);
  163.     fs = fabs(valmin);
  164.     il = 0;
  165.     while (!((fl < 1.0) && (fs < 1.0))) {
  166.         fl /= 10;
  167.         fs /= 10;
  168.         il++;
  169.     }
  170.     while (!((fl >= 0.1) || (fs >= 0.1))) {
  171.         fl *= 10;
  172.         fs *= 10;
  173.         il -= 1;
  174.     }
  175.  
  176.     is = il + ir;
  177.     it = is;
  178.     if ((valmin <= 0.0) && (fmax >= 0.0)) goto LABEL50;
  179.     LABEL40 :
  180.     fl = ((double) modf(fl, &dtemp1)) *10;
  181.     fs = ((double) modf(fs, &dtemp2)) *10;
  182.     if (it <= 0) {
  183.         closegraph();
  184.         Dispatch->Nrerror("Axis: error 16 in axis ");
  185.     }
  186.  
  187.     if (((int) floor(fl)) != ((int) floor(fs))) goto LABEL50;
  188.     it--;
  189.     goto LABEL40;
  190.  
  191.     LABEL50 :
  192.     *ifact = 0;
  193.     *offset = 0.0;
  194.     *irprin = (ir > 0) ? ir : 0;
  195.     ilprin = (il > 0) ? il : 0;
  196.  
  197.     if (((*irprin) + ilprin) <= maxpr) goto LABEL70;
  198.     if (is <= maxpr) goto LABEL60;
  199.     *irprin = maxpr - 1;
  200.     *ifact = (it > maxpr) ? it : maxpr;
  201.     *ifact = (*ifact) - 1 - ir;
  202.     goto LABEL70;
  203.     LABEL60 :
  204.     *ifact = il - 1;
  205.     *irprin = is - 1;
  206.     LABEL70 :
  207.     fs = exp(- ((double) (*ifact)) *log(10.0));
  208.     vstep = step*fs;
  209.     vmin = valmin*fs;
  210.     if (!(is <= maxpr)) {
  211.         *offset = floor(vmin / 10.0) *10;
  212.         vmin -= (*offset);
  213.     }
  214.     for (i = 0; i < nvals; i++) {
  215.         vals[i] = vmin;
  216.         vmin += vstep;
  217.     }
  218.     fs = pow(0.1, ((double) (*irprin)));
  219.     temp1 = fabs(vals[0]) *fs + 0.5;
  220.     temp2 = fabs(vals[nvals - 1]) * fs + 0.5;
  221.     if ((temp1 < tmax) && (temp2 < tmax)) return;
  222.     il++;
  223.     is++;
  224.     it++;
  225.     goto LABEL50;
  226.  
  227. }     /* end axis */
  228.  
  229. /* get scale and axis Applied Statistics algorithm 168 */
  230.  
  231. void Axis::getvals(double fmn, double fmx, int n, double *vals,
  232.     double *offset, int *ifact, int *nvals, int *irprin)
  233. {
  234.  
  235.     scale(fmn, fmx, n, mpv, &valmin, &step, nvals, &ir, &ifault);
  236.     axis(valmin, step, *nvals, maxpr, ir, irprin, offset, ifact,
  237.         vals, iv, &ifault);
  238.  
  239.     //
  240.     // the following code fixes an axis where data is out of range
  241.     //
  242.  
  243.     double st = Rescale(step);
  244.     double t = Rescale(fmn);
  245.     double trace;
  246.     int down = 0, up = 0;
  247.  
  248.     if (t < vals[0])
  249.         for (trace = vals[0]; (t < trace) && (down + *nvals < iv);
  250.             down++, trace -= st);
  251.  
  252. t = Rescale(fmx);
  253. if (t > vals[*nvals - 1])
  254.     for (trace = vals[*nvals - 1]; (t > trace) && (up + down + *nvals < iv);
  255.         up++, trace += st);
  256.  
  257. if (down + up + *nvals >= iv) {
  258.     // prevent a writeover past the end of vals
  259.     ifault = 8;
  260.     char buf[80] = { '\0' };
  261.     sprintf(buf, "Axis: bad parameters in axis: error %d", ifault);
  262.     closegraph();
  263.     Dispatch->Nrerror(buf);
  264. }
  265.  
  266. t = vals[0] - ((double) down) *st;
  267. for (int i = 0; i < down + up + *nvals; i++) {
  268.     vals[i] = t;
  269.     t += st;
  270. }
  271. *nvals += down + up;
  272. }
  273. strtype Axis::GetAxisLabel(strtype &name)
  274. {
  275.     char xo[20] = { '\0' }, xi[20] = { '\0' };
  276. char buf[80] = { '\0' };
  277. strtype newname;
  278. newname = name + " ";
  279.  
  280. gcvt(offset, 8, buf);
  281. strcpy(xo, (const char *) buf);
  282. gcvt(ifact, 8, buf);
  283. strcpy(xi, (const char *) buf);
  284. if (offset && ifact)
  285.     newname = newname + "((x+" + xo + ")*10**" + xi + ")";
  286. if (!offset && ifact)
  287.     newname = newname + "(x*10**" + xi + ")";
  288. if (offset && !ifact)
  289.     newname = newname + "(x+" + xo + ")";
  290. return newname;
  291. }
  292. double Axis::Rescale(double x)
  293. {
  294.     static double log10 = log(10.0);
  295.     double xo = x + offset;
  296.     double si = (xo <= 0.0) ? - 1.0 : 1.0;
  297.     double xv = (xo == 0.0) ? 0.0 :
  298.     si*exp(log(fabs(xo)) - ((double) ifact) *log10);
  299.     return xv;
  300. }
  301.  
  302.  
  303. //////////////////////// yaxis
  304.  
  305.  
  306. YAxis::YAxis(VMatrix &grf, int xxlen, int yylen, int ww, int hh,
  307.     int bbmarg, int uumarg, int llmarg, int rrmarg) :
  308. Axis(grf, 4, yylen, yylen / hh)
  309. {
  310.     Dispatch->Inclevel();
  311.     h = hh;
  312.     w = ww;
  313.     bmarg = bbmarg;
  314.     umarg = uumarg;
  315.     lmarg = llmarg;
  316.     rmarg = rrmarg;
  317.     ylen = yylen;
  318.     xlen = xxlen;
  319.  
  320.     maxy =(Mmax(*Vals)).m(3, 1);
  321.     miny =(Mmin(*Vals)).m(3, 1);
  322.  
  323.     deltay =(fabs(maxy - miny) < 1.0e-10) ? 1.1*miny : maxy - miny;
  324.     deltay =((double) ylen) / deltay;
  325.  
  326.     Dispatch->Cleanstack();
  327.     Dispatch->Declevel();
  328. }
  329.  
  330.  
  331.  
  332. void YAxis::Show(boolean gridon)
  333. {
  334.     // show yaxis
  335.  
  336.     char *buf = new char[80];
  337.     strtype *junk = new strtype;
  338.     setviewport(lmarg, umarg, rmarg, bmarg, 1);
  339.     line(0, 0, 0, ylen + 1);
  340.  
  341.     setviewport(0, umarg - h, lmarg, bmarg + h, 1);
  342.     settextjustify(RIGHT_TEXT, CENTER_TEXT);
  343.  
  344.     int tickloc;
  345.     for (int i = 1; i <= nvals; i++) {
  346.         double temp = Vals->m(i, 1);
  347.         tickloc = ylen - (int) (deltay*(temp - miny)) + h;
  348.         gcvt(temp, (maxpr + 2), buf);
  349.         *junk = "";
  350.         *junk = *junk + buf + " ";
  351.         outtextxy(lmarg, tickloc, junk->StringAddress());
  352.         line(lmarg - w + 1, tickloc - 1, lmarg, tickloc - 1);
  353.     }
  354.     if (gridon) {
  355.         setviewport(lmarg, umarg - h, rmarg, bmarg + h, 1);
  356.         setlinestyle(lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
  357.         for (int i = 1; i <= nvals; i++) {
  358.             double temp = Vals->m(i, 1);
  359.             tickloc = ylen - (int) (deltay*(temp - miny)) + h;
  360.             line(0, tickloc - 1, xlen, tickloc - 1);
  361.  
  362.         }
  363.         setlinestyle(lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
  364.     }
  365.  
  366.     setviewport(lmarg, umarg, rmarg, bmarg, 1);
  367.     delete buf;
  368.     delete junk;
  369.  
  370.  
  371. }
  372. //////////// xaxis
  373.  
  374. XAxis::XAxis(VMatrix &grf, int xxlen, int yylen, int ww, int hh,
  375.     int bbmarg, int uumarg, int llmarg, int rrmarg) :
  376. Axis(grf, 3, xxlen, xxlen / ww)
  377. {
  378.     Dispatch->Inclevel();
  379.     xlen = xxlen;
  380.     ylen = yylen;
  381.     w = ww;
  382.     h = hh;
  383.     bmarg = bbmarg;
  384.     umarg = uumarg;
  385.     lmarg = llmarg;
  386.     rmarg = rrmarg;
  387.  
  388.     maxx =(Mmax(*Vals)).m(3, 1);
  389.     minx =(Mmin(*Vals)).m(3, 1);
  390.  
  391.     deltax =(fabs(maxx - minx) < 1.0e-10) ? 1.1*minx : maxx - minx;
  392.     deltax =((double) xlen) / deltax;
  393.  
  394.     Dispatch->Cleanstack();
  395.     Dispatch->Declevel();
  396.  
  397. }
  398.  
  399. void XAxis::Show(boolean gridon)
  400. {
  401.     char *buf = new char[80];
  402.     setviewport(lmarg, umarg, rmarg, bmarg, 1);
  403.     line(0, ylen, xlen, ylen);
  404.  
  405.  
  406.     int mdelta = w*(maxpr + 2) / 2 + w;
  407.     setviewport(lmarg - mdelta, bmarg, rmarg + mdelta, bmarg + 5*h, 1);
  408.     settextjustify(CENTER_TEXT, TOP_TEXT);
  409.  
  410.     int tickloc;
  411.     for (int i = 1; i <= nvals; i++) {
  412.         double temp = Vals->m(i, 1);
  413.         tickloc = mdelta + (int) (deltax*(temp - minx));
  414.         gcvt(temp, (maxpr + 2), buf);
  415.         outtextxy(tickloc, h, buf);
  416.         line(tickloc + 1, 0, tickloc + 1, h / 2);
  417.     }
  418.  
  419.     if (gridon) {
  420.         setviewport(lmarg - mdelta, umarg, rmarg + mdelta, bmarg, 1);
  421.         setlinestyle(lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
  422.         for (int i = 1; i <= nvals; i++) {
  423.             double temp = Vals->m(i, 1);
  424.             tickloc = mdelta + (int) (deltax*(temp - minx));
  425.             line(tickloc + 1, 0, tickloc + 1, ylen);
  426.         }
  427.         setlinestyle(lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
  428.     }
  429.  
  430.     setviewport(lmarg, umarg, rmarg, bmarg, 1);
  431.     delete buf;
  432. }
  433.  
  434.  
  435. ///////////////////////////////  graph matrix class
  436.  
  437. GMatrix::GMatrix(void)
  438. {
  439.     title = new strtype;
  440.     title2 = new strtype;
  441.     xname = new strtype;
  442.     yname = new strtype;
  443.     PathToDriver = new strtype;
  444.     hrefs = new double[20];
  445.     vrefs = new double[20];
  446.  
  447.  
  448.     graphnum = 0;
  449.     nhrefs = nvrefs = -1;
  450.     RectangleOn = TTRUE;
  451.     XGridOn = YGridOn = FFALSE;
  452.     grf = new VMatrix("graph", 1, 4);
  453. }
  454.  
  455. GMatrix::GMatrix(VMatrix &ROp, int symbol)
  456. {
  457.     Dispatch->Inclevel();
  458.  
  459.     nvrefs = nhrefs = -1;
  460.  
  461.     title = new strtype;
  462.     *title = ROp.Getname(ROp);
  463.     title2 = new strtype;
  464.     xname = new strtype;
  465.     yname = new strtype;
  466.     PathToDriver = new strtype;
  467.     hrefs = new double[20];
  468.     vrefs = new double[20];
  469.  
  470.     graphnum = 1;
  471.     RectangleOn = TTRUE;
  472.     XGridOn = YGridOn = FFALSE;
  473.     grf = new VMatrix("graph", 1, 4);
  474.     int n = ROp.r;
  475.     printf("\nMaking a Graph\n");
  476.     *grf =
  477.     Ch(Fill(n, 1, (double) graphnum), Ch(Fill(n, 1, (double) symbol), ROp));
  478.     Dispatch->Declevel();
  479. }
  480.  
  481. GMatrix::~GMatrix(void)
  482. {
  483.     delete grf;
  484.     delete title;
  485.     delete title2;
  486.     delete xname;
  487.     delete yname;
  488.     delete PathToDriver;
  489.     delete hrefs;
  490.     delete vrefs;
  491. }
  492. void GMatrix::Href(double href)
  493. {
  494.     hrefs[++ nhrefs % 20] = href;
  495. }
  496.  
  497. void GMatrix::Vref(double vref)
  498. {
  499.     vrefs[++ nvrefs % 20] = vref;
  500. }
  501.  
  502.  
  503.  
  504. void GMatrix::AddVec(VMatrix &ROp, int symbol)
  505. {
  506.     Dispatch->Inclevel();
  507.     VMatrix *temp = new VMatrix;
  508.     graphnum++;
  509.     int n = ROp.r;
  510.     printf("\nAppending a new graph\n");
  511.     *temp =
  512.     Ch(Fill(n, 1, (double) graphnum), Ch(Fill(n, 1, (double) symbol), ROp));
  513.     *grf = Cv(*grf, *temp);
  514.     delete temp;
  515.     Dispatch->Declevel();
  516. }
  517.  
  518. int GMatrix::gprintf(int *xloc, int *yloc, char *fmt,...)
  519. {
  520.     va_list argptr;     // Argument list pointer
  521.     char str[140];     // Buffer to build sting into
  522.     int cnt;     // Result of SPRINTF for return
  523.  
  524.     va_start(argptr, fmt);     // Initialize va_ functions
  525.  
  526.     cnt = vsprintf(str, fmt, argptr);     // prints string to buffer
  527.     outtextxy(*xloc, *yloc, str);     // Send string in graphics mode
  528.     *yloc += textheight("H") + 2;     // Advance to next line
  529.     va_end(argptr);     // Close va_ functions
  530.     return (cnt);     // Return the conversion count
  531.  
  532. }
  533. void GMatrix::Pause(void)
  534. {
  535.     static char msg[] = "Esc aborts or press a key...";
  536.     int c;
  537.     c = getch();
  538.     if (0x1b == c) {
  539.         closegraph();
  540.         exit(1);
  541.     }
  542.     if (0 == c) {
  543.         c = getch();
  544.     }
  545.     cleardevice();
  546.     restorecrtmode();
  547. }
  548.  
  549. void GMatrix::plotpoint(int ix, int iy, int symbol)
  550. {
  551.     char str[2] = { (char) symbol, '\0' };
  552.     outtextxy(ix, iy, str);
  553. }
  554.  
  555. void GMatrix::Show(void)
  556. {
  557.  
  558.     Dispatch->Inclevel();
  559.     GraphDriver = DETECT;
  560.     // GraphDriver = CGA;
  561.     // GraphMode = CGAHI;
  562.     initgraph(&GraphDriver, &GraphMode, PathToDriver->StringAddress());
  563.     ErrorCode = graphresult();
  564.     if (ErrorCode != grOk) {
  565.         printf(" Graphics System Error: %s\n", grapherrormsg(ErrorCode));
  566.         exit(1);
  567.     }
  568.  
  569.     cleardevice();
  570.  
  571.     MaxX = getmaxx();
  572.     MaxY = getmaxy();     // Read size of screen
  573.  
  574.     getviewsettings(&viewinfo);
  575.     getlinesettings(&lineinfo);
  576.     setcolor(MaxColors - 1);
  577.     MaxColors = getmaxcolor() + 1;
  578.     setcolor(MaxColors - 1);
  579.     //Black on white for screen captures for EGA/VGA
  580.     if (GraphDriver == VGA || GraphDriver == EGA ){
  581.        setbkcolor(WHITE);
  582.        setpalette(1,BLACK);
  583.        setcolor( 1 );
  584.     }
  585.  
  586.     setviewport(0, 0, MaxX, MaxY, 1);
  587.     settextjustify(CENTER_TEXT, CENTER_TEXT);
  588.     int x = MaxX / 2, y = 4;
  589.     gprintf(&x, &y, title->StringAddress());
  590.     gprintf(&x, &y, title2->StringAddress());
  591.     int h = textheight("H");
  592.     int w = textwidth("Z");
  593.     int lmarg = 10*w, rmarg = MaxX - 10 * w, umarg = 5*h, bmarg = MaxY - 5*h;
  594.  
  595.     setviewport(lmarg, umarg - 1, rmarg, bmarg, 1);
  596.     getviewsettings(&viewinfo);
  597.     int xlen = viewinfo.right - viewinfo.left;
  598.     int ylen = viewinfo.bottom - viewinfo.top;
  599.  
  600.     setlinestyle(lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
  601.     if (RectangleOn) rectangle(0, 0, xlen, ylen);
  602.  
  603.  
  604.     ///////////// draw axies
  605.     YAxis *yaxis = new YAxis(*grf, xlen, ylen, w, h, bmarg, umarg, lmarg, rmarg);
  606.     yaxis->Show(YGridOn);
  607.  
  608.     XAxis *xaxis = new XAxis(*grf, xlen, ylen, w, h, bmarg, umarg, lmarg, rmarg);
  609.     xaxis->Show(XGridOn);
  610.  
  611.     ////////////// plot points
  612.  
  613.     setlinestyle(lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
  614.  
  615.     setviewport(lmarg, umarg, rmarg, bmarg, 1);
  616.     settextjustify(CENTER_TEXT, CENTER_TEXT);
  617.  
  618.     int lx, ly, ix, iy, cnter = 1;
  619.     boolean newgraph = TTRUE;
  620.     double deltax = ((double) xlen) / (xaxis->maxx - xaxis->minx);
  621.     double deltay = ((double) ylen) / (yaxis->maxy - yaxis->miny);
  622.     for (int i = 1; i <= grf-> r; i++) {
  623.         if (cnter != ((int) grf->m(i, 1))) {
  624.             cnter++;
  625.             newgraph = TTRUE;
  626.         }
  627.         double symbol = grf->m(i, 2);
  628.         double tempx = xaxis->Rescale(grf->m(i, 3));
  629.         double tempy = yaxis->Rescale(grf->m(i, 4));
  630.         ix = (int) ((tempx - xaxis->minx) *deltax);
  631.         iy = ylen - (int) ((tempy - yaxis->miny) *deltay);
  632.         plotpoint(ix, iy, abs(symbol));
  633.         if (symbol <= 0.0) {
  634.             if (!newgraph) line(lx, ly, ix, iy);
  635.             newgraph = FFALSE;
  636.         }
  637.         lx = ix;
  638.         ly = iy;
  639.     }
  640.  
  641.     if (nhrefs > - 1) {
  642.         int indx = (nhrefs > 19) ? 19 : nhrefs;
  643.         for (i = 0; i <= indx; i++) {
  644.             double temph = yaxis->Rescale(hrefs[i]);
  645.             iy = ylen -((int) ((temph - yaxis->miny) *deltay));
  646.             line(0, iy, xlen, iy);
  647.         }
  648.     }
  649.     if (nvrefs > - 1) {
  650.         int indx = (nvrefs > 19) ? 19 : nvrefs;
  651.         for (i = 0; i <= indx; i++) {
  652.             double tempv = xaxis->Rescale(vrefs[i]);
  653.             ix = (int) ((tempv - xaxis->minx) *deltax);
  654.             line(ix, 0, ix, ylen);
  655.         }
  656.     }
  657.  
  658.     /////////// display axis labels
  659.     setviewport(0, 0, MaxX, MaxY, 1);
  660.     strtype *ylabel = new strtype;
  661.     *ylabel = yaxis->GetAxisLabel(*yname);
  662.     x = lmarg;
  663.     y = umarg - h - 3;
  664.     gprintf(&x, &y, ylabel->StringAddress());
  665.  
  666.     strtype *xlabel = new strtype;
  667.     *xlabel = xaxis->GetAxisLabel(*xname);
  668.     y = bmarg + 3*h + h / 2 + 2;
  669.     x = MaxX / 2;
  670.     gprintf(&x, &y, xlabel->StringAddress());
  671.  
  672.     Pause();
  673.     delete xaxis;
  674.     delete yaxis;
  675.     delete xlabel;
  676.     delete ylabel;
  677.     Dispatch->Cleanstack();
  678.     Dispatch->Declevel();
  679.  
  680. }
  681.